package com.ctsi.ssdc.utils;

import com.ctsi.ssdc.common.CallBackResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;

import java.util.concurrent.*;

@Slf4j
public class ExcelThreadPool {

    private ExecutorService threadPoolExecutor;
    private CountDownLatch countDownLatch;
    private boolean isFail;
    private CopyOnWriteArrayList<Exception> exceptions = new CopyOnWriteArrayList<>();
    private TransactionTemplate transactionTemplate;
//    private JpaTransactionManager transactionManager;

    public ExcelThreadPool(int size, TransactionTemplate transactionTemplate) {
        this.threadPoolExecutor = Executors.newFixedThreadPool(size);
        this.countDownLatch = new CountDownLatch(size);
//        this.transactionManager = transactionManager;
        this.transactionTemplate = transactionTemplate;
    }

    public void submit(Callable<CallBackResult> callable) {
        // 编程式事务
        threadPoolExecutor.submit(() -> {
            transactionTemplate.execute(new TransactionCallbackWithoutResult() {
                @Override
                protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
                    CallBackResult call = null;
                    try {
                        call = callable.call();
                    } catch (Exception e) {
                        isFail = true;
                        exceptions.add(call.getException());
                    } finally {
                        if (!call.isOk()) {
                            isFail = true;
                            exceptions.add(call.getException());
                        }
                        countDownLatch.countDown();
                    }
                }
            });
        });
    }

    public boolean await(Runnable failCallback) {
        await(30, TimeUnit.SECONDS);
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        threadPoolExecutor.shutdown();
        if (isFail) {
            log.error("处理任务报错!!!下面是报错消息!~");
            for (Exception exception : exceptions) {
                exception.printStackTrace();
            }
            failCallback.run();
            return false;
        }
        if (countDownLatch.getCount() > 0) {
            log.error("任务超时~请检查事务死锁");
            failCallback.run();
            return false;
        }
        log.info("执行完成~!");
        return true;
    }

    public void await(int time, TimeUnit timeUnit) {
        try {
            countDownLatch.await(time, timeUnit);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

}
